package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
	"time"
)

type StructA struct {
	FieldA string `form:"field_a"`
}

type StructB struct {
	NestedStruct StructA
	FieldB       string `form:"field_b"`
}

type StructC struct {
	NestedStructPointer *StructA
	FieldC              string `form:"field_c"`
}

type StructD struct {
	NestedAnonyStruct struct {
		FieldX string `form:"field_x"`
	}
	FieldD string `form:"field_d"`
}
type StructE struct {
	Name     string `form:"name"`
	Age      int8   `form:"age"`
	UserName string `form:"userName"`
	UseDate  string `form:"useDate" time_format: "2020-12-22 12:22:22" time_utc:"1" `
}
type Person struct {
	ID   string `uri:"id" binding:"required,uuid"`
	Name string `uri:"name" binding:"required"`
}
type UrlParams struct {
	ID   string `uri:"id" binding:"required,uuid"`
	Name string `uri:"name" binding:"required"`
}

func main() {
	r := gin.Default()

	// 控制台日志设置颜色
	//	gin.ForceConsoleColor()
	// 关闭控制台颜色
	gin.DisableConsoleColor()
	f, _ := os.Create("gin-learn.log")
	gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
	/*	r.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
		// your custom format
		return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
			param.ClientIP,
			param.TimeStamp.Format(time.RFC1123),
			param.Method,
			param.Path,
			param.Request.Proto,
			param.StatusCode,
			param.Latency,
			param.Request.UserAgent(),
			param.ErrorMessage,
		)
	}))*/
	//r.Use(Logger())
	//	r.Use(gin.Recovery())
	// 日志格式化方法
	gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
		log.Printf("endpointttttttttttttttttttt %v %v %v %v\n", httpMethod, absolutePath, handlerName, nuHandlers)
	}
	// 请求分组
	group := r.Group("/test", func(c *gin.Context) {
		c.JSON(200, "/test")
	})

	// 渲染html，加载模板文件
	r.LoadHTMLGlob("tmpl/*")

	m := make(map[string]string)
	m["test"] = "test"
	group.GET("/ping", func(c *gin.Context) {
		//c.JSON(200,gin.H{
		//	"message": "pong",
		//})
		c.JSON(200, m)

	})
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})

	})
	r.GET("/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "index"})
	})
	r.GET("/asciiJOSN", func(c *gin.Context) {
		m["lang"] = "GO语言"
		m["tag"] = "<br>"
		c.AsciiJSON(200, m)
	})
	r.GET("/mapping", TestParamMapping)
	r.GET("/mappingDate", TestMappingDate)
	r.GET("/bindingUrl/:name/:id", TestBindingUrl)
	r.GET("/:name/:id", func(c *gin.Context) {
		var person Person
		if err := c.ShouldBindUri(&person); err != nil {
			c.JSON(400, gin.H{"msg": err})
			return
		}
		c.JSON(200, gin.H{"name": person.Name, "uuid": person.ID})
	})
	r.POST("/post", func(c *gin.Context) {
		ids := c.QueryMap("ids")
		names := c.PostFormMap("names")
		//array := c.PostFormArray("id")
		array, _ := c.GetPostFormArray("id")
		form, _ := c.GetPostForm("id")
		fmt.Println(form)
		fmt.Println(array)
		fmt.Printf("ids: %v; names: %v ; arr: %v", ids, names, array)
		c.JSON(200, gin.H{"msg": "success", "status": "0"})
	})
	r.POST("/postBody", func(c *gin.Context) {
		var p Person
		c.Bind(&p)
		//c.JSON(200, p)}) //gin.H{"name":p.Name,"id":p.ID})
		c.JSON(200, gin.H{"name": p.Name, "id": p.ID})
	})
	r.Run()

}
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()

		// Set example variable
		c.Set("example", "12345")

		// before request

		c.Next()

		// after request
		latency := time.Since(t)
		log.Print(latency)

		// access the status we are sending
		status := c.Writer.Status()
		log.Println(status)
	}
}

func TestBindingUrl(c *gin.Context) {
	var u UrlParams
	if err := c.ShouldBindUri(&u); err != nil {
		c.JSON(400, gin.H{"msg": err.Error()})
		return
	}
	c.JSON(200, gin.H{"name": u.Name, "id": u.ID})
}

func TestMappingDate(c *gin.Context) {
	var t StructE
	if c.ShouldBind(&t) == nil {
		c.JSON(200, gin.H{"date": t.UseDate})
	}
}

func TestParamMapping(c *gin.Context) {
	var t StructE
	c.Bind(&t)
	c.JSON(200, gin.H{
		"name":     t.Name,
		"age":      t.Age,
		"userName": t.UserName,
	})
}

func TestPingRoute(t *testing.T) {
	router := gin.Default()

	w := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "http://127.0.0.1:8080/ping", nil)
	router.ServeHTTP(w, req)

	assert.Equal(t, 200, w.Code)
	assert.Equal(t, "pong", w.Body.String())
}
